package com.dhecp.project.hr.service.impl;

import com.dhecp.common.core.domain.AjaxResult;
import com.dhecp.common.utils.MessageUtils;
import com.dhecp.common.utils.RandomValueUtils;
import com.dhecp.common.utils.TypeUtils;
import com.dhecp.core.constant.DataFiltering;
import com.dhecp.core.utils.PageUtils;
import com.dhecp.core.utils.ReflectUtils;
import com.dhecp.project.common.domain.ModuleNID;
import com.dhecp.project.common.domain.RecordCheck;
import com.dhecp.project.common.domain.UpdateFlow;
import com.dhecp.project.common.service.impl.BaseModuleServiceImpl;
import com.dhecp.project.flowable.mapper.SysProcessInstanceMapper;
import com.dhecp.project.storage.domain.StockControl;
import com.dhecp.project.storage.domain.StockControlRunning;
import com.dhecp.project.storage.domain.StockUpdate;
import com.dhecp.project.storage.mapper.StockControlMapper;
import com.dhecp.project.storage.mapper.StockControlRunningMapper;
import com.dhecp.project.storage.mapper.StockUpdateMapper;
import com.dhecp.project.storage.service.StockUpdateService;
import com.dhecp.project.system.service.SysDictionaryForFieldService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class StockUpdateServiceImpl extends BaseModuleServiceImpl implements StockUpdateService {

    @Autowired
    private StockUpdateMapper businessMapper;
    @Autowired
    private SysDictionaryForFieldService dictionaryForFieldService;
    @Autowired
    private StockControlMapper storageMapper;

    @Autowired
    private StockControlRunningMapper stockControlRunningMapper;


    @Override
    public List<StockUpdate> queryList(Map<String, Object> params) throws Exception {
        params.put(DataFiltering.TABLE_ALIAS, "t1");    //查询表别名
        params.put(DataFiltering.DATA_WHERE, dictionaryForFieldService.getWhereStr(params));    //常规查询条件SQL语句
        params.put(DataFiltering.DATA_SCODE, dictionaryForFieldService.getDataScode(params));    //数据权限查询条件SQL语句
        if (params.get("field") == null || params.get("field") == ""){
            String orderBy = "t1.createTime DESC";
            PageUtils.startPageOrder(orderBy);
        }else{
            PageUtils.startPage();
        }
        return businessMapper.select(params);
    }

    @Override
    public StockUpdate queryFirstRecord(Map<String, Object> params) throws Exception {
        params.put(DataFiltering.TABLE_ALIAS, "t1");    //查询表别名
        params.put(DataFiltering.DATA_SCODE, dictionaryForFieldService.getDataScode(params));    //数据权限查询条件SQL语句
        return businessMapper.selectFirstRecordByNid(params);
    }

    /**
     * 查询指定单nid的整单录
     * @param nid 必要参数：当前 单据编码
     * @return List - StockUpdate
     * @throws Exception
     * @author DH-Xxj
     */
    @Override
    public List<StockUpdate> queryListByNid(Map<String, Object> params) throws Exception {
        params.put(DataFiltering.TABLE_ALIAS, "t1");	//查询表别名
//        params.put(DataFiltering.DATA_SCODE, dictionaryForFieldService.getDataScode(params));	//数据权限查询条件SQL语句
        return businessMapper.selectByNid(params);
    }

    @Override
    public List<StockUpdate> queryKcYp(Map<String, Object> params) throws Exception {
        params.put(DataFiltering.TABLE_ALIAS, "t1");	//查询表别名
//        params.put(DataFiltering.DATA_WHERE, dictionaryForFieldService.getWhereStr(params));	//常规查询条件SQL语句
        params.put(DataFiltering.DATA_SCODE, dictionaryForFieldService.getDataScode(params));	//数据权限查询条件SQL语句


        if (params.get("field") == null || params.get("field") == ""){
            String orderBy = "t1.productCode asc";
            PageUtils.startPageOrder(orderBy);
        }else{
            PageUtils.startPage();
        }

        return businessMapper.queryKcYp(params);
    }

    @SuppressWarnings("unchecked")
    @Override
    @Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
    public AjaxResult saveData(Map<String, Object> params) {
        params.put("businessEntity", new StockUpdate());
        AjaxResult ajaxResult = this.saveDataBase(params);
        if (!"0".equals(ajaxResult.get("code").toString())){
            throw new RuntimeException(ajaxResult.get("msg").toString());
        }
        String resNid = "0";
        Map<String, Object> infoMap = (Map<String, Object>) ajaxResult.get("infoMap");
        List<StockUpdate> businessDataList = (List<StockUpdate>) ajaxResult.get("businessDataList");

        List<RecordCheck> guidMapList = businessMapper.findRecords(infoMap.get("nid").toString());
        Map<String, Object> guidMap = new HashMap<String, Object>();
        if (!guidMapList.isEmpty() && guidMapList.size() > 0){
            if (infoMap.get("newNid") != null && "1".equals(infoMap.get("newNid").toString())){ //单号重复验证
                throw new RuntimeException(MessageUtils.message("module.error.retry"));
            }
            for (RecordCheck recordCheck : guidMapList){
                if (recordCheck != null && recordCheck.getGuid() != null){
                    guidMap.put(recordCheck.getGuid().toString(), "1");
                }
            }
        }
        if (businessDataList == null || businessDataList.size() == 0){
            resNid = "0";
        }else{
            resNid = infoMap.get("nid").toString();
            for (StockUpdate businessData : businessDataList) {
                //判断该数据是否被其他单据使用
                int count = businessMapper.countGuidKc(businessData.getGuidKc(),businessData.getGuid());
                if (count != 0){
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    return AjaxResult.error("数据异常,请刷新后再操作!");
                }
                String guid = "";
                if (businessData.getGuid() == null){
                    guid = RandomValueUtils.getGUID();
                    businessData.setGuid(guid);
                }else{
                    guid = businessData.getGuid().toString();
                }


                for (String field : infoMap.keySet()){ //遍历非网格字段，并赋值到实体中
                    Object fieldValue = infoMap.get(field);
                    ReflectUtils.setValue(businessData, field, fieldValue);
                }

                if (guidMap.get(guid) == null){
                    businessMapper.insert(businessData);
                }else{
                    businessMapper.update(businessData);
                    guidMap.remove(guid);
                }
            }
        }

        if (!guidMap.isEmpty()){
            for (String guid : guidMap.keySet()){
                businessMapper.delete(guid);
            }
        }

        return AjaxResult.success(MessageUtils.message("module.success.issuccess"),resNid);
    }

    /**
     *@Description: 查询前一单NID、BID
     *@Param: [params] nid 必要参数：当前 单据编码
     *@return: com.dhecp.common.core.domain.AjaxResult  (data.nid 前一单NID， data.bid 前一单BID)
     *@Author: hlf
     *@date: 2022-05-09 10:08
     */
    @Override
    public AjaxResult queryLastNid(Map<String, Object> params) throws Exception {
        Map<String, Object> dataMap = new HashMap<String, Object>();
        if (params.get("nid") == null || params.get("nid") == ""){
            params.put("nid", "0");
        }
        params.put(DataFiltering.TABLE_ALIAS, "t1");	//查询表别名
        params.put(DataFiltering.DATA_SCODE, dictionaryForFieldService.getDataScode(params));	//数据权限查询条件SQL语句
        ModuleNID moduleNID = businessMapper.selectLastNid(params);
        if (moduleNID == null){
            dataMap.put("nid", "0");
            dataMap.put("bid", "0");
            return AjaxResult.warn(MessageUtils.message("module.warn.isfirstnid"), TypeUtils.mapToJson(dataMap).toString());
        }
        dataMap.put("nid", moduleNID.getNid().toString());
        dataMap.put("bid", moduleNID.getBid().toString());
        return AjaxResult.success(MessageUtils.message("module.success.issuccess"), TypeUtils.mapToJson(dataMap).toString());
    }


    /**
     *@Description: 查询后一单NID、BID
     *@Param: [params] nid 必要参数：当前 单据编码
     *@return: com.dhecp.common.core.domain.AjaxResult  (data.nid 后一单NID， data.bid 后一单BID)
     *@Author: hlf
     *@date: 2022-05-09 10:09
     */
    @Override
    public AjaxResult queryNextNid(Map<String, Object> params) throws Exception {
        Map<String, Object> dataMap = new HashMap<String, Object>();
        if (params.get("nid") == null || params.get("nid") == "" || "0".equals(params.get("nid").toString())){
            dataMap.put("nid", "0");
            dataMap.put("bid", "0");
            return AjaxResult.warn(MessageUtils.message("module.warn.isfinallynid"), TypeUtils.mapToJson(dataMap).toString());
        }
        params.put(DataFiltering.TABLE_ALIAS, "t1");	//查询表别名
        params.put(DataFiltering.DATA_SCODE, dictionaryForFieldService.getDataScode(params));	//数据权限查询条件SQL语句
        ModuleNID moduleNID = businessMapper.selectNextNid(params);
        if (moduleNID == null){
            dataMap.put("nid", "0");
            dataMap.put("bid", "0");
            return AjaxResult.warn(MessageUtils.message("module.warn.isfinallynid"), TypeUtils.mapToJson(dataMap).toString());
        }
        dataMap.put("nid", moduleNID.getNid().toString());
        dataMap.put("bid", moduleNID.getBid().toString());
        return AjaxResult.success(MessageUtils.message("module.success.issuccess"), TypeUtils.mapToJson(dataMap).toString());
    }


    /**
     *@Description: 流转  —— 添加流程任务、修改流程状态及生效标志
     *@Param: [params] tableDataId 必要参数：单据编码（nid）
     *@return: com.dhecp.common.core.domain.AjaxResult
     *@Author: hlf
     *@date: 2022-05-09 10:11
     */
    @Override
    @Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
    public AjaxResult updateFlowGo(Map<String, Object> params) {
        Map<String, Object> infoMap = new HashMap<String, Object>();
        String nid = "0";
        if (params.get("tableDataId") == null || params.get("tableDataId") ==""){
            return AjaxResult.error(MessageUtils.message("module.error.lack","单据编码【tableDataId】"));
        }else{
            nid = params.get("tableDataId").toString();
        }
        params.put("nid", nid);
        List<StockUpdate> businessDataList = businessMapper.selectByNid(params);
        if (businessDataList == null || businessDataList.size() == 0){
            return AjaxResult.error(MessageUtils.message("module.error.nodata"));
        }else{
            infoMap.put("cid", businessDataList.get(0).getCid());
            infoMap.put("bUser", businessDataList.get(0).getbUser());
            infoMap.put("bDept", businessDataList.get(0).getbDept());
            infoMap.put("procInstId", businessDataList.get(0).getProcInstId());
            infoMap.put("activeFlow", businessDataList.get(0).getActiveFlow());
            infoMap.put("createTime", businessDataList.get(0).getCreateTime());
            params.put("infoMap", TypeUtils.mapToJson(infoMap).toString());
            params.put("activeFlowOld", businessDataList.get(0).getActiveFlow());
        }

        //流程处理公共方法，返回单据（流转、回退等）后的流程状态信息
        if (params.get("optType") == null || params.get("optType") == ""){
            params.put("optType", "go");
        }

        UpdateFlow updateFlow = new UpdateFlow();
        updateFlow = this.FlowDealBase(params);

        for (StockUpdate businessData : businessDataList) {
            if (updateFlow.getActiveFlow().equals("end")) {//当流程结束时
                //判断是否可用数量=总数量
                StockControl stockControl = storageMapper.findByGuid(businessData.getGuidKc());
                if (stockControl != null) {
                    if (!stockControl.getProductNum().equals(stockControl.getProductNumAll())) {
                        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                        return AjaxResult.error("商品编码:" + businessData.getProductCode() + ",可用数量不等于商品总数量,请核实后再操作!");
                    }
                } else {
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    return AjaxResult.error("商品编码:" + businessData.getProductCode() + "可用数量不等于商品总数量,请核实后再操作!");
                }

                //出入库库存
                updateNum(businessData, stockControl, 0);
            }
            updateFlow.setGuid(businessData.getGuid().toString());
            businessMapper.updateFlow(updateFlow);
        }

        return AjaxResult.success(MessageUtils.message("module.success.issuccess"), nid);
    }

    /**
     *@Description: 退回  —— 添加流程任务、修改流程状态及生效标志
     *@Param: [params] tableDataId 必要参数：单据编码（nid）
     *@return: com.dhecp.common.core.domain.AjaxResult
     *@Author: hlf
     *@date: 2022-05-09 10:11
     */
    @Override
    @Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
    public AjaxResult updateFlowBack(Map<String, Object> params) {
        Map<String, Object> infoMap = new HashMap<String, Object>();
        String nid = "0";
        if (params.get("tableDataId") == null || params.get("tableDataId") ==""){
            return AjaxResult.error(MessageUtils.message("module.error.lack","单据编码【tableDataId】"));
        }else{
            nid = params.get("tableDataId").toString();
        }
        params.put("nid", nid);
        List<StockUpdate> businessDataList = businessMapper.selectByNid(params);
        if (businessDataList == null || businessDataList.size() == 0){
            return AjaxResult.error(MessageUtils.message("module.error.nodata"));
        }else{
            infoMap.put("cid", businessDataList.get(0).getCid());
            infoMap.put("bUser", businessDataList.get(0).getbUser());
            infoMap.put("bDept", businessDataList.get(0).getbDept());
            infoMap.put("procInstId", businessDataList.get(0).getProcInstId());
            infoMap.put("activeFlow", businessDataList.get(0).getActiveFlow());
            infoMap.put("createTime", businessDataList.get(0).getCreateTime());
            params.put("infoMap", TypeUtils.mapToJson(infoMap).toString());
            params.put("activeFlowOld", businessDataList.get(0).getActiveFlow());
        }

        //流程处理公共方法，返回单据（流转、回退等）后的流程状态信息
        if (params.get("optType") == null || params.get("optType") == ""){
            params.put("optType", "back");
        }
        UpdateFlow updateFlow = new UpdateFlow();
        updateFlow = this.FlowDealBase(params);

        for (StockUpdate businessData : businessDataList) {
            if (infoMap.get("activeFlow").equals("end")){
                //判断是否可用数量=总数量
                StockControl stockControl = storageMapper.findByGuid(businessData.getGuidKcP());
                if (stockControl != null) {
                    if (!stockControl.getProductNum().equals(stockControl.getProductNumAll())) {
                        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                        return AjaxResult.error("商品编码:" + businessData.getProductCode() + ",可用数量不等于商品总数量,请核实后再操作!");
                    }
                } else {
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    return AjaxResult.error("商品编码:" + businessData.getProductCode() + "可用数量不等于商品总数量,请核实后再操作!");
                }

                //出入库库存
                updateNum(businessData, stockControl, 1);
            }

            updateFlow.setGuid(businessData.getGuid().toString());
            businessMapper.updateFlow(updateFlow);
        }

        return AjaxResult.success(MessageUtils.message("module.success.issuccess"), nid);
    }

    private void updateNum(StockUpdate stockUpdate,StockControl stockControl, Integer tpye){
        StockControl oldData = new StockControl();
        BeanUtils.copyProperties(stockControl,oldData);
        if (tpye == 0) {
            oldData.setGuid(RandomValueUtils.getGUID());
            oldData.setProductCode(stockUpdate.getuProductCode());
            oldData.setProductName(stockUpdate.getuProductName());
            oldData.setCreateTime(new Date());
            storageMapper.insert(oldData);

            stockControl.setProductNum(0);
            stockControl.setProductNumAll(0);
            storageMapper.update(stockControl);

            stockUpdate.setGuidKcP(oldData.getGuid());
            //将修改优品库存修改单的新的库存id
            businessMapper.update(stockUpdate);

            //新增旧库存流水
            addStockControlRunning(stockUpdate,stockControl, 0, oldData);
            //新增新库存流水
            addStockControlRunning(stockUpdate,stockControl, 1, oldData);
        }else{
            //将新的库存删除
            storageMapper.deleteStockControl(stockControl.getGuid());
            //将旧的数量还原
            StockControl stockContro2 = storageMapper.findByGuid(stockUpdate.getGuidKc());
            stockContro2.setProductNum(stockUpdate.getProductNum());
            stockContro2.setProductNumAll(stockUpdate.getProductNumAll());
            storageMapper.update(stockContro2);

            stockUpdate.setGuidKcP("");
            businessMapper.update(stockUpdate);

            //新增旧库存流水
            addStockControlRunning(stockUpdate,stockControl, 2, stockContro2);
            //新增新库存流水
            addStockControlRunning(stockUpdate,stockControl, 3, stockContro2);
        }

    }

    private void addStockControlRunning(StockUpdate stockUpdate,StockControl stockControl, Integer tpye,StockControl oldData){
        // 新库存添加库存流水
        StockControlRunning stockControlRunning = new StockControlRunning();
        stockControlRunning.setGuid(RandomValueUtils.getGUID());
        stockControlRunning.setBidRelative(stockUpdate.getBid());
        stockControlRunning.setLocationHw(stockControl.getvHw());
        stockControlRunning.setProductCode(stockControl.getProductCode());
        stockControlRunning.setvGsBm(stockUpdate.getvGsBm());
        stockControlRunning.setCreateTime(new Date());
        if (tpye == 0) {
            stockControlRunning.setGuidStockControl(stockControl.getGuid());
            stockControlRunning.setProductNumChange(-stockUpdate.getProductNum());
            stockControlRunning.setProductNumLeft(0);
            stockControlRunning.setRemark("优品库存流转将"+stockControl.getGuid() +"转至"+ oldData.getGuid());
        }else if (tpye == 1) {
            stockControlRunning.setGuidStockControl(oldData.getGuid());
            stockControlRunning.setProductNumChange(stockUpdate.getProductNum());
            stockControlRunning.setProductNumLeft(stockUpdate.getProductNum());
            stockControlRunning.setRemark("优品库存流转新增库存,"+oldData.getGuid());
        }if (tpye == 2) {
            stockControlRunning.setGuidStockControl(oldData.getGuid());
            stockControlRunning.setProductNumChange(stockUpdate.getProductNum());
            stockControlRunning.setProductNumLeft(stockUpdate.getProductNumAll());
            stockControlRunning.setRemark("优品库存退回将"+stockControl.getGuid() +"转至"+ oldData.getGuid());
        }if (tpye == 3) {
            stockControlRunning.setGuidStockControl(stockControl.getGuid());
            stockControlRunning.setProductNumChange(-stockControl.getProductNum());
            stockControlRunning.setProductNumLeft(0);
            stockControlRunning.setRemark("优品库存退回删除库存"+ oldData.getGuid());
        }
        stockControlRunningMapper.insert(stockControlRunning);
    }
}
